package com.xuexiang.xuidemo.page.base;

import ohos.agp.components.BaseItemProvider;
import ohos.agp.components.Component;
import ohos.agp.components.ComponentContainer;
import ohos.app.Context;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

/**
 * BaseProvider
 *
 * @param <E> 数据泛型
 * @since 2021-03-25
 */
public abstract class BaseProvider<E> extends BaseItemProvider {
    private static final int INT_NONE = -1;
    /**
     * 页面的Tag
     */
    protected final String tag = getClass().getSimpleName();
    /**
     * 上下文
     */
    protected final Context mContext;
    private final ArrayList<E> mDatas = new ArrayList<>();
    private OnItemClickEvent<E> onItemClickEvent;

    /**
     * 构造器
     *
     * @param context 上下文
     * @param datas 数据集合
     */
    public BaseProvider(Context context, List<E> datas) {
        this.mContext = context;
        if (datas != null) {
            mDatas.addAll(datas);
        }
    }

    /**
     * 重置该Provider数据并刷新
     *
     * @param datas 数据
     */
    public void reSetAndNotify(List<? extends E> datas) {
        this.mDatas.clear();
        if (datas != null && datas.size() > 0) {
            this.mDatas.addAll(datas);
        }
        notifyDataChanged();
    }


    /**
     * 清除该Provider所有数据
     */
    public void clear() {
        this.mDatas.clear();
    }

    @Override
    public void onItemMoved(int from, int to) {
        super.onItemMoved(from, to);
    }

    /**
     * 设置item点击事件监听
     *
     * @param onItemClickEvent 监听回调接口
     */
    public void setOnItemClickEvent(OnItemClickEvent<E> onItemClickEvent) {
        this.onItemClickEvent = onItemClickEvent;
    }

    @Override
    public int getCount() {
        return mDatas.size();
    }

    @Override
    public long getItemId(int position) {
        return position;
    }

    @Override
    public Component getComponent(int position, Component component, ComponentContainer componentContainer) {
        BaseHolder<E> holder;
        Component temp = component;
        if (temp == null) {
            holder = onCreateItemHolder(mContext, position);
            temp = holder.itemComponent;
            temp.setTag(holder);
        } else {
            holder = (BaseHolder<E>) temp.getTag();
        }
        E item = getItem(position);
        holder.onBindComponent(position, item);
        temp.setClickedListener(component1 -> {
            if (onItemClickEvent != null) {
                onItemClickEvent.onItemClick(holder.itemComponent, position, item);
            }
        });
        return temp;
    }

    /**
     * 重置Provider数据
     *
     * @param datas 数据集合
     */
    public void setData(List<? extends E> datas) {
        this.mDatas.clear();
        if (datas != null) {
            this.mDatas.addAll(datas);
        }
    }

    /**
     * 重置Provider数据
     *
     * @param datas 数据数组
     */
    public void setData(E[] datas) {
        this.mDatas.clear();
        if (datas != null) {
            this.mDatas.addAll(Arrays.asList(datas));
        }
    }

    /**
     * 添加数据
     *
     * @param datas 要添加的数据集合
     */
    public void addData(List<? extends E> datas) {
        if (datas != null && datas.size() > 0) {
            this.mDatas.addAll(datas);
        }
    }

    /**
     * 添加数据
     *
     * @param index 位置
     * @param datas 要添加的数据数据
     */
    public void addData(int index, List<E> datas) {
        if (index >= 0 && index <= mDatas.size()) {
            if (datas != null && datas.size() > 0) {
                this.mDatas.addAll(index, datas);
            }
        }
    }

    /**
     * 添加数据
     *
     * @param index 位置
     * @param data 要添加的数据
     */
    public void addData(int index, E data) {
        this.mDatas.add(index, data);
    }

    /**
     * 添加数据
     *
     * @param datas 要添加的数据
     */
    public void addData(E[] datas) {
        if (datas != null && datas.length > 0) {
            this.mDatas.addAll(Arrays.asList(datas));
        }
    }

    /**
     * 添加数据
     *
     * @param data 要添加的数据
     * @return 告知添加成功状态
     */
    public boolean addData(E data) {
        if (data != null) {
            this.mDatas.add(data);
            return true;
        }
        return false;
    }

    /**
     * 添加数据
     *
     * @param datas 要添加的数据集合
     */
    public void addDatas(List<? extends E> datas) {
        this.mDatas.addAll(datas);
    }

    /**
     * 添加数据到头部
     *
     * @param data 要添加的数据
     */
    public void addDataToFirst(E data) {
        if (data != null) {
            this.mDatas.add(0, data);
        }
    }

    /**
     * 添加数据到头部
     *
     * @param list 要添加的数据集合
     */
    public void addDataToFirst(List<E> list) {
        if (list != null) {
            this.mDatas.addAll(0, list);
        }
    }

    /**
     * 移除指定数据
     *
     * @param data 要移除的数据
     * @return 告知移除是否成功
     */
    public boolean removeData(E data) {
        if (data != null) {
            return this.mDatas.remove(data);
        }
        return false;
    }

    /**
     * 移除指定位置的数据
     *
     * @param index 要移植数据的位置
     * @return 被移除的数据
     */
    public E removeData(int index) {
        if (index >= 0 && index < mDatas.size()) {
            return this.mDatas.remove(index);
        }
        return null;
    }

    /**
     * 清除所有数据
     */
    public void clearData() {
        this.mDatas.clear();
    }

    /**
     * 返回数据列表
     *
     * @return 数据列表
     */
    public List<E> getDatas() {
        return this.mDatas;
    }

    /**
     * 返回列表大小
     *
     * @return 数据大小
     */
    public int getDatasSize() {
        return this.mDatas.size();
    }

    /**
     * 修改数据, 该需要需要重写重写 Object#equals方法,以便匹配到到该对象
     *
     * @param data 修改后的数据
     */
    public void modifyData(E data) {
        if (this.mDatas.contains(data)) {
            int index = this.mDatas.indexOf(data);
            if (index != INT_NONE) {
                this.mDatas.remove(index);
                this.mDatas.add(index, data);
            }
        }
    }

    /**
     * 修改指定位置的数据
     *
     * @param position 要修改的位置
     * @param data 要修改的数据
     */
    public void modifyData(int position, E data) {
        if (position >= 0 && position < mDatas.size() && data != null) {
            this.mDatas.remove(position);
            this.mDatas.add(position, data);
        }
    }

    /**
     * 返回最后一条数据
     *
     * @return 最后一条数据
     */
    public E getLastItem() {
        return getItem(mDatas.size() - 1);
    }

    /**
     * 返回指定位置的数据
     *
     * @param position 指定位置
     * @return 指定位置的数据
     */
    public E getItem(int position) {
        if (position >= 0 && position < this.mDatas.size()) {
            return this.mDatas.get(position);
        } else {
            return null;
        }
    }

    /**
     * 创建ItemHolder, 子类必须实现该方法
     *
     * @param context 上下文
     * @param position 位置
     * @return BaseHolder
     */
    public abstract BaseHolder<E> onCreateItemHolder(Context context, int position);

    /**
     * BaseProvider.Item点击回调接口
     *
     * @param <E> 数据泛型
     * @since 2021-03-25
     */
    public interface OnItemClickEvent<E> {
        /**
         * Item点击事件回调
         *
         * @param component Item最外层组件
         * @param position 数据的索引位置
         * @param data 数据
         */
        void onItemClick(Component component, int position, E data);
    }
}
